package main

import (
	"bigdevops/src/cache"
	"bigdevops/src/common"
	"bigdevops/src/config"
	"bigdevops/src/cron"
	"bigdevops/src/models"
	"bigdevops/src/rpc"
	"bigdevops/src/web"
	"context"
	"flag"
	"fmt"
	esl "github.com/ning1875/errgroup-signal/signal"
	"go.uber.org/zap"
	"os"
)

func main() {

	// 定义命令行参数，用于接收主配置文件路径
	var (
		configFile string
	)
	flag.StringVar(&configFile, "config_file", "./server.yml", "The config yml")
	flag.Parse()

	// 加载主配置文件
	sc, err := config.LoadServer(configFile)
	if err != nil {
		fmt.Printf("解析主配置文件错误:%v\n", err)
		return
	}

	// 创建本地 yaml 文件夹
	err = os.MkdirAll(sc.LocalYamlDir, os.ModePerm)
	if err != nil {
		fmt.Printf("创建本地yaml文件夹失败:%v\n", err)
		return
	}

	// 初始化 logger
	logger := common.NewZapLogger(sc.LogLevel, sc.LogFilePath)
	defer logger.Sync() // 确保缓冲区中的日志数据被写入文件
	sc.Logger = logger
	logger.Info("解析主配置文件成功 logger初始化成功")

	// 初始化数据库
	err = models.InitDb(sc.MysqlC.DSN)
	if err != nil {
		logger.Error("初始化gorm-db错误", zap.Error(err))
		return
	}
	logger.Info("初始化gorm-db成功")

	// 初始化 Casbin
	err = models.InitCasbin(sc)
	if err != nil {
		logger.Error("初始化casbin错误", zap.Error(err))
		return
	}
	logger.Info("初始化casbin成功")

	// 同步表结构
	err = models.MigrateTable()
	if err != nil {
		logger.Error("gorm-db同步表结构错误", zap.String("错误", err.Error()))
		return
	}
	logger.Info("gorm-db同步表结构成功")

	// 根据配置决定是否注入模拟数据
	if sc.NeedMockData {
		logger.Info("配置开启mock数据，开始注入测试数据")
		models.InsertBasicDbData(sc)
	} else {
		logger.Info("配置关闭mock数据，跳过注入测试数据")
	}

	// 初始化任务管理器和各模块的缓存
	cm := cron.NewCronManager(sc)
	tc := cache.NewTaskCache(sc)
	mc := cache.NewMonitorCache(sc)
	streeC := cache.NewStreeCache(sc)
	kc := cache.NewK8sClusterCache(sc)

	// 初始化 GitLab 客户端
	gitlabClient, err := cache.NewGitlabClient(sc)
	if err != nil {
		logger.Error("初始化cicd模块用到的gitlabClient-报错", zap.Error(err))
		return
	}

	// 设置退出信号管理
	group, stopChan := esl.SetupStopSignalContext()
	ctxAll, cancelAll := context.WithCancel(context.Background())

	// 监听退出信号
	group.Go(func() error {
		logger.Info("[stopchan监听启动]")
		for {
			select {
			case <-stopChan:
				logger.Info("捕获退出信号 停止ctx 通知所有任务退出")
				cancelAll()
				return nil
			}
		}
	})

	// 启动同步公有云任务
	if sc.PublicCloudSyncC.Enable {
		group.Go(func() error {
			logger.Info("计划任务--同步公有云--启动")
			err := cm.SyncCloudResourceManager(ctxAll)
			if err != nil {
				logger.Error("计划任务--同步公有云--报错", zap.Error(err))
			}
			return err
		})
	} else {
		logger.Info("计划任务--同步公有云--关闭")
	}

	// 启动工单自动执行模块
	if sc.WorkOrderAutoActionC.Enable {
		group.Go(func() error {
			logger.Info("计划任务--工单自动执行模块--启动")
			err := cm.AutoOrderManager(ctxAll)
			if err != nil {
				logger.Error("计划任务--工单自动执行模块--报错", zap.Error(err))
			}
			return err
		})
	} else {
		logger.Info("计划任务--工单自动执行模块--关闭")
	}

	// 启动工单通知模块
	if sc.WorkOrderAutoActionC.Enable {
		group.Go(func() error {
			logger.Info("计划任务--工单通知模块--启动")
			err := cm.NotifyOrderManager(ctxAll)
			if err != nil {
				logger.Error("计划任务--工单通知模块--报错", zap.Error(err))
			}
			return err
		})
	} else {
		logger.Info("计划任务--工单通知模块--关闭")
	}

	// 启动监控值班历史设置任务
	group.Go(func() error {
		logger.Info("计划任务--监控值班历史设置--启动")
		err := cm.FullFillOnDutyHistoryManager(ctxAll)
		if err != nil {
			logger.Error("计划任务--监控值班历史设置--报错", zap.Error(err))
		}
		return err
	})

	// 启动任务执行模块
	if sc.JobExecC.Enable {
		group.Go(func() error {
			logger.Info("计划任务--任务执行模块--启动")
			err := tc.TaskCacheManager(ctxAll)
			if err != nil {
				logger.Error("计划任务--任务执行模块--报错", zap.Error(err))
			}
			return err
		})
	} else {
		logger.Info("计划任务--任务执行模块--关闭")
	}

	// 启动监控模块缓存
	if sc.MonitorComputeC.Enable {
		group.Go(func() error {
			logger.Info("计划任务--监控模块-缓存启动")
			err := mc.MonitorCacheManager(ctxAll)
			if err != nil {
				logger.Error("计划任务--监控模块--报错", zap.Error(err))
			}
			return err
		})
	} else {
		logger.Info("计划任务--监控模块--关闭")
	}

	// 启动服务树模块缓存
	if sc.StreeCacheC.Enable {
		group.Go(func() error {
			logger.Info("计划任务--服务树模块-缓存启动")
			err := streeC.StreeCacheManager(ctxAll)
			if err != nil {
				logger.Error("计划任务--服务树模块--报错", zap.Error(err))
			}
			return err
		})
	} else {
		logger.Info("计划任务--服务树模块--关闭")
	}

	// 启动 K8s 模块缓存
	if sc.K8sClusterC.Enable {
		group.Go(func() error {
			logger.Info("计划任务--k8s模块--启动")
			err := kc.K8sClusterCacheManager(ctxAll)
			if err != nil {
				logger.Error("计划任务--k8s模块--报错", zap.Error(err))
			}
			return err
		})
	} else {
		logger.Info("计划任务--k8s模块--关闭")
	}

	// 启动 Gin Web 服务器
	group.Go(func() error {
		errChan := make(chan error, 1)
		go func() {
			errChan <- web.ServerStartGin(sc, streeC, mc, kc, gitlabClient)
		}()
		logger.Info("web启动成功")
		select {
		case err := <-errChan:
			logger.Error("gin报错", zap.Error(err))
			return err
		case <-ctxAll.Done():
			logger.Info("gin收到其他任务退出信号 退出")
			return nil
		}
	})

	// 启动 gRPC 服务器
	group.Go(func() error {
		errChan := make(chan error, 1)
		go func() {
			errChan <- rpc.StartServerGrpc(sc, tc)
		}()
		select {
		case err := <-errChan:
			logger.Error("grpc报错", zap.Error(err))
			return err
		case <-ctxAll.Done():
			logger.Info("grpc收到其他任务退出信号 退出")
			return nil
		}
	})

	// 等待所有 goroutine 结束
	group.Wait()
}
